package yxy.game.pm2.module.mail;

import org.joda.time.DateTime;
import org.redisson.api.RList;
import org.redisson.api.RMap;
import yxy.apple.util.RandomStringUtility;
import yxy.apple.util.redisson.RedisException;
import yxy.cherry.game.base.redis.RedisManager;
import yxy.game.pm2.bean.Currency;
import yxy.game.pm2.bean.area.AreaBean;
import yxy.game.pm2.bean.currency.CurrencyType;
import yxy.game.pm2.bean.db.newDao.MailDAO;
import yxy.game.pm2.bean.db.po.MailPo;
import yxy.game.pm2.bean.module.AreaModule;
import yxy.game.pm2.bean.module.BaseGameRedisLockBean;
import yxy.game.pm2.bean.mq.CCReason;
import yxy.game.pm2.module.tip.TipHandle;
import yxy.game.pm2.module.tip.TipType;

import java.util.*;
import java.util.stream.Collectors;

public class MailBean extends BaseGameRedisLockBean {

	// bean===========================================================================
	private String code;// 编码
	private MailTypeEnum type;// 标题
	private String title;// 标题
	private String content;// 内容
	private ArrayList<Currency> rewards = new ArrayList<>();
	private CCReason reason;// 奖励原因
	private boolean readed; // 已读
	private boolean rewarded;// 已领奖
	private DateTime sendTime;// 发送时间
	private DateTime expiryTime;// 过期时间

	public String getCode() {
		return code;
	}

	public void setCode(String code) {
		this.code = code;
	}

	public MailTypeEnum getType() {
		return type;
	}

	public void setType(MailTypeEnum type) {
		this.type = type;
	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public String getContent() {
		return content;
	}

	public void setContent(String content) {
		this.content = content;
	}

	public ArrayList<Currency> getRewards() {
		return rewards;
	}

	public void setRewards(ArrayList<Currency> rewards) {
		this.rewards = rewards;
	}

	public CCReason getReason() {
		return reason;
	}

	public void setReason(CCReason reason) {
		this.reason = reason;
	}

	public boolean isReaded() {
		return readed;
	}

	public void setReaded(boolean readed) {
		this.readed = readed;
	}

	public boolean isRewarded() {
		return rewarded;
	}

	public void setRewarded(boolean rewarded) {
		this.rewarded = rewarded;
	}

	public DateTime getSendTime() {
		return sendTime;
	}

	public void setSendTime(DateTime sendTime) {
		this.sendTime = sendTime;
	}

	public DateTime getExpiryTime() {
		return expiryTime;
	}

	public void setExpiryTime(DateTime expiryTime) {
		this.expiryTime = expiryTime;
	}

	// func==========================================================================

	/** 失效 */
	public boolean expired() {
		return DateTime.now().isAfter(getExpiryTime());
	}
	// redis==========================================================================

	static public String key(String playerCode) {
		return String.format("PLAYER:%s:MAIL", playerCode);
	}

	static public String keySysMail(int areaId) {
		return String.format("SYSTEM:%s:MAIL", areaId);
	}

	static public String keySysMailStatus(String playerCode) {
		return String.format("PLAYER:%s:SYS_MAIL_STATUS", playerCode);
	}

	static private RList<String> touchSysMailStatus(String playerCode) throws RedisException {
		return RedisManager.client(redis()).getList(keySysMailStatus(playerCode));
	}

	static public RMap<String, MailBean> touchSysMail(int areaId) throws RedisException {
		return RedisManager.client(redis()).getMap(keySysMail(areaId));
	}

	static public void delSysMail(int areaId,String code) throws RedisException {
		RedisManager.client(redis()).getMap(keySysMail(areaId)).remove(code);
	}

	static public void createToSystem(int areaId, MailBean mail) throws RedisException {
		RedisManager.client(redis()).getMap(keySysMail(areaId)).put(randomCode(), mail);
	}

	static public boolean setSysMailStatus(String pcode, String mailCode) {
		try {
			RedisManager.client(redis()).getList(keySysMailStatus(pcode)).add(mailCode);
			return true;
		} catch (RedisException e) {
			e.printStackTrace();
			return false;
		}
	}

	static private RMap<String, MailBean> touch(String playerCode) throws RedisException {
		return RedisManager.client(redis()).getMap(key(playerCode));
	}

	static public Map<String, MailBean> all(String playerCode) {
		try {
			RMap<String, MailBean> rMap = touch(playerCode);
			if (!rMap.isExists()) { //redis key 不存在，则从db取
				List<MailPo> all = MailDAO.getList(playerCode);
				Map<String, MailBean> mails = all.stream().collect(Collectors.toMap(MailPo::getCode, MailBean::toBean, (a, b) -> b, HashMap::new));
				rMap.putAll(mails);
			}
			return rMap.readAllMap();
		} catch (RedisException e) {
			e.printStackTrace();
		}

		return new HashMap<>();
	}

	static public void saveToDB(String playerCode){
		try {
			RMap<String, MailBean> map = touch(playerCode);
			if (map.isExists()) {
				long updateTime = System.currentTimeMillis();
				if (map.size() > 0) {
					List<MailPo> collect = map.values().stream().map(b -> toDbBean(playerCode, b)).collect(Collectors.toList());
					MailDAO.replace(playerCode, collect, updateTime);
				}

				MailDAO.delete(playerCode, updateTime);
			}
		} catch (Exception e){
			e.printStackTrace();
		}
	}

	static public MailBean get(String playerCode, String code) {
		try {
            MailBean mail = touch(playerCode).get(code);
            return mail;
		} catch (Exception e) {
			return null;
		}
	}

	static public boolean set(String playerCode, MailBean mail) {
		try {
            touch(playerCode).put(mail.code, mail);
            check(playerCode);
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	static public MailBean create(String playerCode, MailBean mail) throws RedisException {
		String code = randomCode();
		Map<String, MailBean> mails = all(playerCode);
		while (mails.containsKey(code)) {
			code = randomCode();
		}

		mail.setCode(code);
		set(playerCode, mail);
		return mail;
	}

	static private String randomCode() {
		return String.format("mm%s", RandomStringUtility.randomLowerNumeric(4));
	}

	public static void remove(String playerCode, String code) {
		try {
            touch(playerCode).remove(code);
			MailDAO.deleteByCode(playerCode, code);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void remove(String playerCode, Collection<String> codes) {
		try {
			RMap<String, MailBean> mails = touch(playerCode);
			for (String code : codes) {
				mails.remove(code);
				MailDAO.deleteByCode(playerCode, code);
			}
            check(playerCode);
        } catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void removeAllFromRedis(String playerCode) {
		try {
			touch(playerCode).delete();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void checkSystemMail(String pcode){
		try {
			AreaBean areaBean = AreaModule.area(pcode);
			int areaId = areaBean.getAreaId();
			RMap<String, MailBean> sysMail = touchSysMail(areaId);
			Set<String> strings = sysMail.keySet();
			if (strings.size() == 0) {
				return;
			}
			RList<String> sysMailStatus = touchSysMailStatus(pcode);
			for (String s : strings) {
				if (!sysMailStatus.contains(s)) {
					MailBean mailBean = sysMail.get(s);
					if (!DateTime.now().isAfter(mailBean.getExpiryTime())){
						create(pcode, mailBean);
						setSysMailStatus(pcode,s);
					}
				}
			}
		} catch (RedisException e) {
			e.printStackTrace();
		}
	}

	/** 查看是否有未读邮件 控制红点 */
	static public void check(String playerCode) {
		try {
			Map<String, MailBean> all = all(playerCode);
			for (MailBean mail : all.values()) {
				if (mail.expired()) {
					continue;
				}
				if (mail.isRewarded()) {
					continue;
				}
				if (!mail.isReaded() || mail.getRewards().size() > 0) {
					new TipHandle().updateTip(playerCode, TipType.主城_邮件按钮, true);
					return;
				}
			}
			new TipHandle().updateTip(playerCode, TipType.主城_邮件按钮, false);
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

    public static ArrayList<Currency> conversion(String rewards){
        ArrayList<Currency> rewards2 = new ArrayList<>();
        if (rewards != null && rewards.length() > 0) {
            String[] split = rewards.split(",");
            for (String str : split) {
                String[] spl = str.trim().split(":");
                Currency currency = Currency.create(CurrencyType.valueOf(spl[0]), Integer.parseInt(spl[1]), Integer.parseInt(spl[2]));
                rewards2.add(currency);
            }
        }
        return rewards2;
    }

    public static MailBean toBean(MailPo mailPo) {
        MailBean m = new MailBean();
        m.setCode(mailPo.getCode());
        m.setType(MailTypeEnum.forNumber(mailPo.getType()));
        m.setTitle(mailPo.getTitle());
        m.setContent(mailPo.getContent());
        m.setRewards(conversion(mailPo.getRewards()));
        m.setReason(CCReason.valueOf(mailPo.getReason()));
        m.setReaded(mailPo.isReaded());
        m.setRewarded(mailPo.isRewarded());
        m.setSendTime(new DateTime(mailPo.getSendTime()));
        m.setExpiryTime(new DateTime(mailPo.getExpiryTime()));
        return m;
    }

    public static MailPo toDbBean(String playerCode, MailBean mail) {
        MailPo m = new MailPo();
        m.setpCode(playerCode);
        m.setCode(mail.getCode());
        m.setType(mail.getType().getNumber());
        m.setTitle(mail.getTitle());
        m.setContent(mail.getContent());
        String s = mail.getRewards().toString();
        s = s.substring(1, s.length() - 1);
        m.setRewards(s);
        m.setReason(mail.getReason().toString());
        m.setReaded(mail.isReaded());
        m.setRewarded(mail.isRewarded());
        m.setSendTime(mail.getSendTime().toDate());
        m.setExpiryTime(mail.getExpiryTime().toDate());
        return m;
    }
}
